﻿using Newtonsoft.Json.Linq;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;

namespace Client {
    /// <summary>
    /// ShotScreen.xaml 的交互逻辑
    /// </summary>
    public partial class ShotScreen : Window {

        private static ShotScreen shotScreen = null;

        private SocketUtil socket = null;

        private double x;
        private double y;
        private double newX;
        private double newY;
        private double width;
        private double height;

        private bool isMouseDown = false;
        SolidColorBrush BlackBrush = new SolidColorBrush(Colors.Black);

        double ScreenX = 0;
        double ScreenY = 0;
        double ScreenW = 0;
        double ScreenH = 0;

        private ShotScreen() {
            InitializeComponent();
            socket = SocketUtil.GetSocket();
        }

        public static ShotScreen GetShotScreen() {
            if (shotScreen == null) {
                shotScreen = new ShotScreen();
            }
            return shotScreen;
        }

        public void Capture() {
            Screen[] screens = Screen.AllScreens;
            foreach (Screen screen in screens) {
                ScreenX = Math.Min(ScreenX, screen.Bounds.X);
                ScreenY = Math.Min(ScreenY, screen.Bounds.Y);

                ScreenW = Math.Max(ScreenW, screen.Bounds.Right);
                ScreenH = Math.Max(ScreenH, screen.Bounds.Bottom);
            }

            Bitmap bitmap = new Bitmap((int)ScreenW, (int)ScreenH);
            using (Graphics graphics = Graphics.FromImage(bitmap)) {
                graphics.CopyFromScreen((int)ScreenX, (int)ScreenY, 0, 0, new System.Drawing.Size((int)ScreenW, (int)ScreenH));

                MemoryStream stream = new MemoryStream();

                bitmap.Save(stream, ImageFormat.Png);

                ImageBrush imageBrush = new ImageBrush();

                ImageSourceConverter imageSourceConverter = new ImageSourceConverter();

                imageBrush.ImageSource = (ImageSource)imageSourceConverter.ConvertFrom(stream);

                Background = imageBrush;
            }

            Left = ScreenX;
            Top = ScreenY;
            Width = ScreenW;
            Height = ScreenH;
            Visibility = Visibility.Visible;

            System.Windows.Shapes.Rectangle BlackRect = new System.Windows.Shapes.Rectangle();
            BlackRect.Fill = BlackBrush;
            BlackRect.Width = Width;
            BlackRect.Height = Height;
            Canvas.SetLeft(BlackRect, Left);
            Canvas.SetTop(BlackRect, Top);
            CaptureCanvas.Children.Add(BlackRect);
        }
        [DllImport("gdi32.dll", SetLastError = true)]
        private static extern bool DeleteObject(IntPtr hObject);

        public static ImageSource ChangeBitmapToImageSource(Bitmap bitmap) {
            IntPtr hBitmap = bitmap.GetHbitmap();
            ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            if (!DeleteObject(hBitmap)) {//记得要进行内存释放。否则会有内存不足的报错。
                throw new System.ComponentModel.Win32Exception();
            }
            return wpfBitmap;
        }

        private void CaptureWindow_MouseDown(object sender, MouseButtonEventArgs e) {
            isMouseDown = true;
            x = e.GetPosition(null).X;
            y = e.GetPosition(null).Y;
        }

        private void CaptureWindow_MouseMove(object sender, MouseEventArgs e) {
            if (isMouseDown == true && e.LeftButton == MouseButtonState.Pressed) {
                // 1. 通过一个矩形来表示目前截图区域
                double dx = e.GetPosition(null).X;
                double dy = e.GetPosition(null).Y;
                width = Math.Abs(dx - x);
                height = Math.Abs(dy - y);

                newX = Math.Min(dx, x);
                newY = Math.Min(dy, y);

                // 四个矩形 红 黄 蓝 绿
                System.Windows.Shapes.Rectangle LeftRect = new System.Windows.Shapes.Rectangle();
                LeftRect.Fill = BlackBrush;
                LeftRect.Width = newX;
                LeftRect.Height = newY + height;
                Canvas.SetLeft(LeftRect, 0);
                Canvas.SetTop(LeftRect, 0);

                System.Windows.Shapes.Rectangle TopRect = new System.Windows.Shapes.Rectangle();
                TopRect.Fill = BlackBrush;
                TopRect.Width = ScreenW - newX;
                TopRect.Height = newY;
                Canvas.SetLeft(TopRect, newX);
                Canvas.SetTop(TopRect, ScreenY);

                System.Windows.Shapes.Rectangle RightRect = new System.Windows.Shapes.Rectangle();
                RightRect.Fill = BlackBrush;
                RightRect.Width = ScreenW - newX - width;
                RightRect.Height = ScreenH - newY;
                Canvas.SetLeft(RightRect, newX + width);
                Canvas.SetTop(RightRect, newY);

                System.Windows.Shapes.Rectangle BottomRect = new System.Windows.Shapes.Rectangle();
                BottomRect.Fill = BlackBrush;
                BottomRect.Width = newX + width;
                BottomRect.Height = ScreenH - newY - height;
                Canvas.SetLeft(BottomRect, ScreenX);
                Canvas.SetTop(BottomRect, newY + height);

                CaptureCanvas.Children.Clear();
                CaptureCanvas.Children.Add(LeftRect);
                CaptureCanvas.Children.Add(TopRect);
                CaptureCanvas.Children.Add(RightRect);
                CaptureCanvas.Children.Add(BottomRect);
            } else if (isMouseDown) {
                isMouseDown = false;
                CaptureScreen(newX, newY, width, height);
            }
        }

        private void CaptureScreen(double x, double y, double width, double height) {
            if (width == 0 || height == 0) return;
            int ix = Convert.ToInt32(x);
            int iy = Convert.ToInt32(y);
            int iw = Convert.ToInt32(width);
            int ih = Convert.ToInt32(height);

            Bitmap bitmap = new Bitmap(iw, ih);
            using (Graphics graphics = Graphics.FromImage(bitmap)) {
                graphics.CopyFromScreen(ix, iy, 0, 0, new System.Drawing.Size(iw, ih));

                string base64 = "data:image/png;base64," + ImgToBase64String(bitmap);

                JObject jObject = new JObject { ["base64"] = base64 };
                socket.Emit("screenshotComplete", jObject);

                Hide();
            }
        }

        public static string ImgToBase64String(Bitmap bmp) {
            try {
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, ImageFormat.Png);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                return Convert.ToBase64String(arr);
            } catch (Exception) {
                return null;
            }
        }

        private void CaptureCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
            Hide();
        }
    }
}
